package xijia.plus.docs.manage.all.service.impl;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ZipUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.github.wslxm.springbootplus2.core.utils.date.LocalDateTimeUtil;
import io.github.wslxm.springbootplus2.file.util.FileDownloadUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import xijia.plus.docs.enums.Yw;
import xijia.plus.docs.manage.all.model.entity.DocInfo;
import xijia.plus.docs.manage.all.model.pojo.SiteMapPOJO;
import xijia.plus.docs.manage.all.model.query.DocCategoryQuery;
import xijia.plus.docs.manage.all.model.vo.DocCategoryVO;
import xijia.plus.docs.manage.all.model.vo.DocConfigVO;
import xijia.plus.docs.manage.all.service.DocCategoryService;
import xijia.plus.docs.manage.all.service.DocConfigService;
import xijia.plus.docs.manage.all.service.DocInfoService;
import xijia.plus.docs.manage.all.service.SiteMapService;
import xijia.plus.docs.thymeleafuser.util.XjFileUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 生成站点地图
 *
 * @author wangsong
 * @version 1.0.0
 * @email 1720696548@qq.com
 * @date 2022/12/25 0025 9:39
 */
@Service
@Slf4j
//@DS("#header.tenantName")
public class SiteMapServiceImpl implements SiteMapService {

    @Autowired
    private HttpServletResponse response;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private DocInfoService docInfoService;

    @Autowired
    private DocCategoryService docCategoryService;

    @Autowired
    private DocConfigService docConfigService;

    /**
     * 主 sitemap.xml 中的每一个下级 sitemap.xml
     *
     * @author wangsong
     * @email 1720696548@qq.com
     * @date 2022/12/25 0025 9:54
     * @version 1.0.0
     */
    private final static String XML_SITEMAP_TEMPLATES = "    <sitemap>\n" +
            "        <loc>{url}</loc> \n" +
            "        <lastmod>{updateTime}</lastmod> \n" +
            "    </sitemap>\n";

    /**
     * 每一个下级的 sitemap.xml
     */
    private final static String XML_URL_TEMPLATES = "    <url>\n" +
            "        <loc>{baseVisitUrl}/{url}</loc> \n" +
            "        <lastmod>{updateTime}</lastmod> \n" +
            "    </url>\n";

    /**
     * 模板地址
     */
    private final static String TEMPLATES_PATH = "/static/templates/seo/";

    /**
     * 生成后保存文件夹 前缀
     */
    private final static String GENERATE_PATH_PREFIX = "sitemap/";
    /**
     * 生成后保存文件夹 (感觉程序变动值)
     */
    String generatePath = "";

    @Override
    @DS("#tenantName")
    public void generateSiteMap(String tenantName) {
        generatePath = GENERATE_PATH_PREFIX + tenantName ;
        String baseUrl = request.getRequestURL().toString().replace(request.getServletPath(), "");
        // 删除原seo 文件夹下所有数据(如果存在)
        FileUtil.del(new File(generatePath));
        // 生成保存生成后的代码文件目录检查是否存在
        XjFileUtil.mkdirFile(generatePath);

        // 获取访问域名和每个子文件生成的数据量
        DocConfigVO docConfigVO = docConfigService.findByCode(tenantName, "seo-generate-sitemap-config");
        String[] generateSitemapConfig = docConfigVO.getContent().split("\\|");
        // sitemap 的访问地址 +   每个sitemap 文件中的 url 数量
        String baseVisitUrl = generateSitemapConfig[0].trim();
        Integer size = Integer.valueOf(generateSitemapConfig[1].trim());

        List<SiteMapPOJO> siteMapPOJOS = this.getSiteMapPOJO(tenantName);
        // 文档 子sitemap.xml
        this.generateSiteMapNext(siteMapPOJOS, baseUrl, baseVisitUrl, size);

        // sitemap css
        this.sitemapCss();

        // 下载压缩包
        File file = new File(generatePath);
        File zip = ZipUtil.zip(file);
        FileDownloadUtil.download(zip, "siteMap.zip", response);
    }


    /**
     * 站点地图 css 文件生成到指定目录
     *
     * @param baseUrl      模板地址路径
     * @param baseVisitUrl 访问地址路径
     * @param size         模板地址路径
     * @author wangsong
     * @email 1720696548@qq.com
     * @date 2022/12/25 0025 10:35
     * @version 1.0.0
     */
    private void generateSiteMapNext(List<SiteMapPOJO> siteMapPOJOS, String baseUrl, String baseVisitUrl, Integer size) {
        StringBuffer xmlSitemaps = new StringBuffer();
        // 处理数据并生成
        // pageNum = 页码 | size = 分页大小 | totalPage总页数
        int pageNum = 1;
        int totalPage = (siteMapPOJOS.size() + size - 1) / size;
        while (pageNum <= totalPage) {
            List<SiteMapPOJO> nextAliases = ListUtil.page(pageNum - 1, size, siteMapPOJOS);
            StringBuilder xmlUrls = new StringBuilder("");
            for (SiteMapPOJO siteMapPOJO : nextAliases) {
                xmlUrls.append(XML_URL_TEMPLATES
                        .replace("{baseVisitUrl}", baseVisitUrl)
                        .replace("{url}", siteMapPOJO.getUrl())
                        .replace("{updateTime}", LocalDateTimeUtil.parse(siteMapPOJO.getUpdateTime(), "yyyy-MM-dd")));
                // log.error("已生成: --> {}/{}/{}.html", baseVisitUrl, docInfo.getName(), docInfo.getName());
            }
            // 生成子数据 soe-xml  (文件路径+示例名：File/seo/sitemap-1.xml)
            String newName = "sitemap_" + pageNum + ".xml";
            this.generateSiteMapNextFile(baseUrl, baseVisitUrl, TEMPLATES_PATH + "page_sitemap.xml", generatePath + "/" + newName, xmlUrls.toString());
            log.error("已生成子文件: --> {}/{}", baseVisitUrl, newName);

            xmlSitemaps.append(XML_SITEMAP_TEMPLATES
                    .replace("{baseVisitUrl}", baseVisitUrl)
                    .replace("{url}", newName)
                    .replace("{updateTime}", LocalDateTimeUtil.parse(LocalDateTime.now(), "yyyy-MM-dd")));
            pageNum++;
        }
        this.generateSiteMapNextFile(baseUrl, baseVisitUrl, TEMPLATES_PATH + "sitemap.xml", generatePath  + "/" + "sitemap.xml", xmlSitemaps.toString());
        log.error("已生成主文件: --> {}/{}", baseVisitUrl, "sitemap.xml");
    }


    /**
     * 站点地图 css 文件生成到指定目录，导出站点地图 static/sitemap.xml / 拷贝到 dict/ 目录下
     *
     * @author wangsong
     * @email 1720696548@qq.com
     * @date 2022/12/25 0025 10:35
     * @version 1.0.0
     */
    private void sitemapCss() {

        XjFileUtil.copyFileByClasspath("static/seo/css/main-sitemap.xsl", generatePath + "/main-sitemap.xsl");
        // 获取
        //  InputStream inputStream = XjFileUtil.getInputStreamByClasspath("static/seo/css/main-sitemap.xsl");
        //  XjFileUtil.uploadFile(inputStream, generatePath, "main-sitemap.xsl");
        log.info("已导出站点地图css文件 --> / main-sitemap.xsl");
    }


    /**
     * 生成 seo xml
     *
     * @param baseUrl           当前服务器访问地址，获取模板使用
     * @param baseVisitUrl      访问域名或ip地址（SitemapXml中的）
     * @param templatesPath     模板文件路径
     * @param generatePath      生成文件路径
     * @param content           生成的seo数据
     * @return boolean
     * @author wangsong
     * @date 2022/11/3 0003 12:06
     * @version 1.0.0
     */
    private boolean generateSiteMapNextFile(String baseUrl, String baseVisitUrl, String templatesPath, String generatePath, String content) {
        // 获取当前服务器地址
        BufferedReader br = null;
        BufferedWriter bw = null;
        try {
            InputStream in = XjFileUtil.getInputStreamByClasspath(templatesPath);
            br = new BufferedReader(new InputStreamReader(in));
            // 获取代码模版文件
            // br = XjFileUtil.getBufferedReaderByUrl(baseUrl + templatesPath);
            bw = new BufferedWriter(new FileWriter(generatePath));
            String line = null;
            while ((line = br.readLine()) != null) {
                // 内容替换并写入
                String newLine = line.replace("{content}", content);
                newLine = newLine.replace("{path}", baseVisitUrl);
                bw.write(newLine);
                bw.newLine();
                bw.flush();
            }
        } catch (Exception e) {
            log.error(e.toString());
        } finally {
            XjFileUtil.close(br);
            XjFileUtil.close(bw);
        }
        return true;
    }


    /**
     * 获取站点地图文件
     *
     * @author wangsong
     * @email 1720696548@qq.com
     * @date 2023/1/18 0018 11:04
     * @version 1.0.0
     */
    private List<SiteMapPOJO> getSiteMapPOJO(String tenantName) {
        List<SiteMapPOJO> siteMapPOJO = new ArrayList<>();
        // 首页
        siteMapPOJO.add(new SiteMapPOJO("首页", "index.html", LocalDateTime.now()));

        // 查询数据
        List<DocInfo> list = docInfoService.list(new LambdaQueryWrapper<DocInfo>()
                .select(DocInfo::getId, DocInfo::getType, DocInfo::getShowType, DocInfo::getName, DocInfo::getUpdateTime)
                .eq(DocInfo::getShowType, Yw.DocShowType.V2.getValue())
                .orderByAsc(DocInfo::getType)
                .orderByAsc(DocInfo::getSort)
        );

        DocCategoryQuery query = new DocCategoryQuery();
        List<DocCategoryVO> docCategoryVos = docCategoryService.list(tenantName, query);
        // 获取类别
        Map<Integer, DocCategoryVO> oocCategoryVOMap = docCategoryVos.stream().collect(Collectors.toMap(DocCategoryVO::getCode, p -> p));

        // pageNum = 页码 | size = 分页大小 | totalPage总页数
        for (DocInfo docInfo : list) {
            DocCategoryVO docCategoryVO = oocCategoryVOMap.get(docInfo.getType());
            if (docCategoryVO == null) {
                log.error("typeName 错误: 没有找到 type=" + docInfo.getType() + " 的类别名称");
            } else {
                siteMapPOJO.add(new SiteMapPOJO(docInfo.getName(), docCategoryVO.getName() + "/" + docInfo.getName() + ".html", docInfo.getUpdateTime()));
            }
        }
        log.error("获取到文档 url 地址数量: --> {}", list.size());
        log.error("总获取到 url 地址数量: --> {}", siteMapPOJO.size());
        return siteMapPOJO;
    }
}
